<template>
  <div class="content">
    <div class="content-left">
      <div class="left-change divider">
        <el-form :model="formData" ref="formData" label-width="80px">
          <el-row>
            <el-col :span="12">
              <el-form-item label="账号" prop="username" required>
                <el-input v-model="formData.username"></el-input>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="密码" prop="password" required>
                <el-input v-model="formData.password"></el-input>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="摄像头IP" prop="ip" required>
                <el-input v-model="formData.ip"></el-input>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="端口" prop="port" required>
                <el-input v-model="formData.port"></el-input>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="通道" prop="channel" required>
                <el-input v-model="formData.channel"></el-input>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label-width="0">
                <el-button type="primary" @click="changeUrlHandle">连接摄像头</el-button>
                <el-button type="primary" @click="playBackHandle">回放</el-button>
                <el-button @click="testPlay" v-show="false"> ss</el-button>
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>
      </div>
      <div class="video-control divider">
        <div style="text-align: center;width: 15rem;">
          <el-slider
              v-model="controlSpeed"
              :min="1"
              :max="6"
          />
          移动速度：{{controlSpeed}}
        </div>
        <div class="el-button-group">
          <div class="btn-box-1">
            <el-button icon="el-icon-d-arrow-left" class="top controlBtn" data-btnType="up"></el-button>
          </div>
          <div class="btn-box-2">
            <el-button icon="el-icon-d-arrow-left" class="left controlBtn"  data-btnType="left"></el-button>
            <el-button icon="el-icon-d-arrow-left" class="right controlBtn" data-btnType="right"></el-button>
          </div>
          <div class="btn-box-1">
            <el-button icon="el-icon-d-arrow-left" class="bottom controlBtn" data-btnType="down"></el-button>
          </div>
        </div>
        <div class="cameraZoomControl">
          <i class="el-icon-zoom-out controlBtn" data-btnType="minus"></i>
          <span>变焦</span>
          <i class="el-icon-zoom-in controlBtn" data-btnType="plus"></i>
        </div>
      </div>
      <div class="audio-control divider">
        <div class="sayImg" @click="recordingHandle">
          <img v-if="!isRecording" height="60" width="60" src="@/assets/wrokImage/htopen.png" alt="">
          <div v-else class="sayImg-to-close">
            <img height="60" src="@/assets/wrokImage/yiliang.png" alt="">
            <img height="60" width="60" src="@/assets/wrokImage/htclose.png" alt="">
          </div>
          <p class="sayImg-txt1">
            <span  v-if="!isRecording">点击开始喊话(再次点击发送)</span>
            <span  v-else>请说话(点击结束喊话)</span>
          </p>
        </div>
      </div>
    </div>
    <div class="content-divider"></div>
    <div class="content-right">
      <video id="video" :src="defaultUrlString" class="videoPlay-box" muted playsinline controls></video>
      <video v-if="testStatus" id="videoTest" :src="urlString" class="videoPlay-box" muted playsinline controls></video>
    </div>

    <el-dialog
        title="回放视频"
        :visible.sync="dialogVisible"
        width="90%"
        top="5vh"
    >
      <VideoPlayBack ref="VideoPlayBack"></VideoPlayBack>
    </el-dialog>
  </div>
</template>

<script>
import flvjs from 'flv.js'
import{ isVideoURL} from '@/utils/tools'
import {cameraControl,audioFileSend} from "@/api/videoPlay";
import VideoPlayBack from "@/views/videoPlay/videoPlayBack.vue";
export default {
  name: 'index',
  components:{VideoPlayBack},
  data(){
    return {
      formData:{
        username: 'admin',
        password: 'ucan1588',
        ip: '192.168.11.13',
        port: '554',
        channel: '1'
      },
      dialogVisible: false,
      flvUrlString: 'https://222.75.110.246:20443/flv/hls/playback_1_ViYf-ahHgz.flv',
      urlString: 'rtsp://admin:ucan1588@192.168.11.13:554/Streaming/Channels/101',
      testStatus: false,
      defaultUrlString: '',
      videoUrl: '',
      webRtcServer: null,
      options: null,
      url: '',
      controlSpeed: 5,
      controlLoading: false,
      isRecording: false,
      streamRef: null,
      mediaRecorder: null,
      dataBuffer: [],
      voiceLoading: false,
      flvPlayer:null,
      webSocketSystem:null,

      stream: null,
      audioContext: null,
      scriptProcessor: null,
      chunks: [],
      cameraInfo: {
        agreement: 'http',
        channel: '1',
        ip: "192.168.11.13",
        port: "80",
        password: "ucan1588",
        username: "admin",
      }
    }
  },
  mounted() {
    console.log(flvjs.isSupported())
    // this.url = { video:location.search.slice(1) };
    this.options = webrtcConfig.options;
    if (typeof URLSearchParams != 'undefined') {
      let params = new URLSearchParams(location.search);
      if (params.has("video") || params.has("audio")) {
        this.url = { video:params.get("video"), audio:params.get("audio") };
      }
      if (params.has("options")) {
        this.options = params.get("options");
      }
    }
    let controlBtns = document.querySelectorAll('.controlBtn')
    if (controlBtns.length){
      for (let i = 0;i<controlBtns.length;i++){
        let type = controlBtns[i].dataset.btntype
        controlBtns[i].addEventListener('mousedown', this.ptzCameraHandle.bind(this, type));
        controlBtns[i].addEventListener('mouseup', this.ptzCameraHandleStop.bind(this, type));
      }
    }
  },
  methods:{
    async recordingHandle(){
      if (!this.webRtcServer)return this.$message.warning('未连接摄像头，无法操作')
      if (!this.isRecording){
        this.startRecording()
      }else{
        this.stopRecording()
      }
    },
    async startRecording(){
      this.stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
      const source = this.audioContext.createMediaStreamSource(this.stream);

      this.scriptProcessor = this.audioContext.createScriptProcessor(4096, 1, 1);
      this.scriptProcessor.onaudioprocess = (event) => {
        const inputBuffer = event.inputBuffer.getChannelData(0);
        this.chunks.push(new Float32Array(inputBuffer));
      };

      source.connect(this.scriptProcessor);
      this.scriptProcessor.connect(this.audioContext.destination);
      this.isRecording = true;
    },
    stopRecording(){
      if (this.scriptProcessor) {
        this.scriptProcessor.disconnect();
        this.scriptProcessor = null;
      }
      if (this.audioContext) {
        this.audioContext.close();
        this.audioContext = null;
      }
      if (this.stream) {
        this.stream.getTracks().forEach(track => track.stop());
        this.stream = null;
      }

      const mergedChunks = this.mergeArrays(this.chunks);
      const wavData = this.encodeWAV(mergedChunks);

      const blob = new Blob([wavData], { type: 'audio/wav' });
      const formData = new FormData();
      formData.append('file', blob, 'recording.wav');
      formData.append('ip', '192.168.11.13');
      formData.append('port', '8000');
      formData.append('username', 'admin');
      formData.append('password', 'ucan1588');

      audioFileSend(formData).then(res=>{
        console.log(res, '================================')
      }).finally(()=>{
        this.chunks = []
      })
      this.isRecording = false
    },
    encodeWAV(samples, sampleRate = 44100) {
      const buffer = new ArrayBuffer(44 + samples.length * 2);
      const view = new DataView(buffer);

      this.writeString(view, 0, 'RIFF');
      view.setUint32(4, 36 + samples.length * 2, true);
      this.writeString(view, 8, 'WAVE');
      this.writeString(view, 12, 'fmt ');
      view.setUint32(16, 16, true);
      view.setUint16(20, 1, true);
      view.setUint16(22, 1, true);
      view.setUint32(24, sampleRate, true);
      view.setUint32(28, sampleRate * 2, true);
      view.setUint16(32, 2, true);
      view.setUint16(34, 16, true);
      this.writeString(view, 36, 'data');
      view.setUint32(40, samples.length * 2, true);

      this.floatTo16BitPCM(view, 44, samples);

      return view;
    },
    writeString(view, offset, string) {
      for (let i = 0; i < string.length; i++) {
        view.setUint8(offset + i, string.charCodeAt(i));
      }
    },
    floatTo16BitPCM(view, offset, input) {
      for (let i = 0; i < input.length; i++, offset += 2) {
        const s = Math.max(-1, Math.min(1, input[i]));
        view.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
      }
    },
    mergeArrays(arrays) {
      const totalLength = arrays.reduce((acc, array) => acc + array.length, 0);
      const result = new Float32Array(totalLength);
      let offset = 0;
      for (const array of arrays) {
        result.set(array, offset);
        offset += array.length;
      }
      return result;
    },

    playBackHandle(){
      // this.dialogVisible = true
      // this.$nextTick(()=>{
      //   this.$refs.VideoPlayBack.init(this.formData)
      // })
      let backUrl = this.$router.resolve({
        name: 'VideoPlayBack',
        query:{
          ...this.formData
        }
      })
      window.open(backUrl.href)
    },

    testPlay(){
      this.testStatus = true
      this.$nextTick(()=>{
        this.webRtcServer = new WebRtcStreamer("videoTest", webrtcConfig.url);
        this.webRtcServer.connect(this.urlString,this.url.audio,this.options);
        console.log(this.defaultUrlString === this.urlString)
      })
    },
    changeUrlHandle(){
      this.$refs.formData.validate(valida=>{
        if (valida){
          const {username, password,ip, port ,channel } = this.formData
          this.defaultUrlString = `rtsp://${username}:${password}@${ip}:${port}/Streaming/Channels/10${channel}`
          console.log(this.url,webrtcConfig.url, '=====', this.options)
          this.webRtcServer = new WebRtcStreamer("video", webrtcConfig.url);
          this.webRtcServer.connect(this.defaultUrlString,this.url.audio,this.options);
          fetch(webrtcConfig.url + "/api/version").then(r => r.text()).then( (response) => {
          });
        }
      })
    },

    async ptzCameraHandle(type){
      if (!this.webRtcServer)return this.$message.warning('未连接摄像头，无法操作')
      console.log(type)
      const p1 = {
        ...this.cameraInfo,
        sensitivity: (this.controlSpeed * 15),
        pan: ['minus', 'plus'].includes(type) ? null : type === 'left' ? -1 : type === 'right' ? 1 : 0 ,
        tilt: ['minus', 'plus'].includes(type) ? null : type === 'down' ? -1 : type === 'up' ? 1 : 0,
        zoom: ['minus', 'plus'].includes(type) ? type === 'minus' ? -1 : type === 'plus' ? 1 : 0 : null,
      }

      const p2 = {
        ...this.cameraInfo,
        sensitivity: (this.controlSpeed * 15),
        pan: ['minus', 'plus'].includes(type) ? null : 0,
        tilt: ['minus', 'plus'].includes(type) ? null : 0,
        zoom: ['minus', 'plus'].includes(type) ? 0 : null
      }
      this.controlLoading = false
      if (['minus', 'plus'].includes(type)){
        await cameraControl(p1)
        // await cameraControl(p2).then(res=>{
        //
        // }).finally(()=>{
        //   this.controlLoading = false
        // })
        console.log('p1:::',p1)
        console.log('p2:::',p2)
      }else{
        await cameraControl(p1)
        // await cameraControl(p2)
        this.controlLoading = false
      }
    },
    async ptzCameraHandleStop(type){
      if (!this.webRtcServer)return this.$message.warning('未连接摄像头，无法操作')
      console.log(11111111)
      const p2 = {
        ...this.cameraInfo,
        sensitivity: (this.controlSpeed * 15),
        pan: ['minus', 'plus'].includes(type) ? null : 0,
        tilt: ['minus', 'plus'].includes(type) ? null : 0,
        zoom: ['minus', 'plus'].includes(type) ? 0 : null
      }
      await cameraControl(p2)
    },
  },
  beforeDestroy() {
    this.webRtcServer.disconnect()
    if (document && document.querySelectorAll('.controlBtn')) {
      let controlBtns = document.querySelectorAll('.controlBtn')
      for (let i = 0;i<controlBtns.length;i++){
        let type = controlBtns[i].dataset.btntype
        controlBtns[i].removeEventListener('mousedown', this.ptzCameraHandle.bind(this, type));
        controlBtns[i].removeEventListener('mouseup', this.ptzCameraHandleStop.bind(this, type));
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.content{
  height: 100vh;
  display: flex;

  .content-left{
    width: 31rem;
    .left-change{
      padding: 1.2rem 1.2rem;
      display: flex;
      .el-button{
        margin-left: 1.2rem;
      }
    }

    .video-control{
      display: flex;
      flex-direction: column;
      justify-content: space-around;
      align-items: center;
      height: 23rem;

      .el-button-group{
        padding: 4px;
        width: 188px;
        height: 188px;
        border-radius: 50%;
        background-color: #c1c4c4;

        .btn-box-1{
          line-height: 1;
          text-align: center;
        }
        .btn-box-2{
          display: flex;
          justify-content: space-between;
        }

        .el-button{
          width: 60px;
          height: 60px;
        }

        .top{
          transform: rotate(90deg);
        }
        .left{
        }
        .right{
          transform: rotate(180deg);
        }
        .bottom{
          transform: rotate(-90deg);
        }
      }


      .cameraZoomControl{
        width: 20rem;
        display: flex;
        justify-content: space-between;
        align-items: center;
        background-color: #e5e5e5;
        padding: 4px 15px;
        border-radius: 6px;

        i{
          font-size: 2rem;
          cursor: pointer;
        }
      }
    }

    .audio-control{
      padding-top: 1.5rem;
      display: flex;
      justify-content: center;
      .sayImg {
        min-width: 6.5rem;
        display: flex;
        align-items: center;
        flex-direction: column;
        justify-content: center;
        font-size: 1rem;
        .sayImg-to-close {
          display: flex;
        }
        .sayImg-txt1 {
          margin-top: 2.3rem;

        }
      }
    }

    .divider{
      border-bottom: 1px solid;
    }
  }
  .content-right{
    flex: 1;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    .videoPlay-box{
      width: 70rem;
    }
  }
  .content-divider{
    width: 1px;
    height: 100%;
    background-color: black;
  }
}
</style>
